Imports Microsoft.Practices.EnterpriseLibrary.Logging
Imports System.IO
Imports System.Timers

''' <summary>
''' multiple instance is not supported due to cpu is always the bottle neck
''' the target scenario is:
''' 1. run BF2ServerLauncher to create or switch server config (no need to press start button)
''' 2. run services.msc and let me log on as the same user as you have logged on,
'''    and set the path to the folder which contains BF2_win32ded.exe (usually the installdir)
''' 3. start me
''' 4. stop me to shutdown server (by killing its process)
''' 5. restart me if server config is changed
''' </summary>
''' <remarks></remarks>
Public Class BF2ServerGuardianService

	Private bf2dir As String
	Private cmd As String
	Private proc As Diagnostics.Process

	Private WithEvents t As Timer

	Private Sub LogError(ByVal msg As String)

		Dim log As New LogEntry()
		log.Message = msg
		log.Severity = TraceEventType.Error

		Dim cats As New List(Of String)()
		cats.Add("Error")
		log.Categories = cats

		Logger.Write(log)

	End Sub

	'Private Sub LogInfo(ByVal msg As String)

	'	Dim log As New LogEntry()
	'	log.Message = msg
	'	log.Severity = TraceEventType.Information
	'	Logger.Write(log)

	'End Sub

	Protected Overrides Sub OnStart(ByVal args() As String)
		' Add code here to start your service. This method should set things
		' in motion so your service can do its work.

		'EventLog1.WriteEntry("In OnStart")

		If args.Length > 0 Then
			'use args
			'Logger.Write(String.Join(", ", args))
			bf2dir = args(0)
			Logger.Write(String.Format("starting from services.msc properties dialog, and reading bf2dir from args(0): {0}", bf2dir))
		ElseIf My.Settings.InstallDir.Length > 0 Then
			bf2dir = My.Settings.InstallDir
			Logger.Write(String.Format("reading bf2dir from app.config file: {0}", bf2dir))
		Else
			bf2dir = CType(Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Electronic Arts\EA Games\Battlefield 2", "InstallDir", Nothing), String)
			Logger.Write(String.Format("reading bf2dir from registry HKEY_LOCAL_MACHINE\SOFTWARE\Electronic Arts\EA Games\Battlefield 2\@InstallDir: {0}", bf2dir))
			If bf2dir Is Nothing Then
				LogError("cannot determine path to Bf2_win32ded.exe. stopping...")
				Me.Stop()
				Exit Sub
			End If
		End If

		Directory.SetCurrentDirectory(bf2dir)

		'cmd = "Bf2_w32ded.exe"

		'If My.Settings.ServerSettings.Length > 0 Then
		'	Dim home As String = Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "Battlefield 2")
		'	Dim con As String = My.Settings.ServerSettings.Replace("@HOME@", home)
		'	If File.Exists(con) Then
		'		cmd = String.Format("{0} +config ""{1}""", cmd, My.Settings.ServerSettings)
		'		LogInfo(String.Format("loading server config file from: {0}", My.Settings.ServerSettings))
		'	Else
		'		LogError(String.Format("server config file not found: {0}", con))
		'		LogInfo("loading server config file from game installdir")
		'	End If
		'Else
		'	LogInfo("loading server config file from game installdir")
		'End If

		'If My.Settings.MapList.Length > 0 Then
		'	Dim home As String = Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "Battlefield 2")
		'	Dim con As String = My.Settings.MapList.Replace("@HOME@", home)
		'	If File.Exists(con) Then
		'		cmd = String.Format("{0} +mapList ""{1}""", cmd, My.Settings.MapList)
		'		LogInfo(String.Format("loading map list file from: {0}", My.Settings.MapList))
		'	Else
		'		LogError(String.Format("map list file not found: {0}", con))
		'		LogInfo("loading map list file from game installdir")
		'	End If
		'Else
		'	LogInfo("loading map list file from game installdir")
		'End If
		cmd = "Bf2_w32ded.exe +config ""@HOME@/ServerConfigs/_serverSettings.con"" +mapList ""@HOME@/ServerConfigs/_mapList.con"""

		't = New Timer(My.Settings.Interval)
		t = New Timer()
		t.AutoReset = False
		t.Start()

		'Me.Stop()

	End Sub

	''' <summary>
	''' shutdown server
	''' </summary>
	''' <remarks></remarks>
	Protected Overrides Sub OnStop()
		' Add code here to perform any tear-down necessary to stop your service.

		'EventLog1.WriteEntry("In OnStop.")

		If proc IsNot Nothing AndAlso Not proc.HasExited Then
			'proc.Close()
			proc.Kill()
		End If

	End Sub

	''' <summary>
	''' not used
	''' </summary>
	''' <remarks></remarks>
	Protected Overrides Sub OnContinue()

		t.Start()

	End Sub

	''' <summary>
	''' not used
	''' </summary>
	''' <remarks></remarks>
	Protected Overrides Sub OnPause()

		t.Stop()

	End Sub
	'Public Sub New()

	'    MyBase.New()

	'    ' This call is required by the Windows Form Designer.
	'    InitializeComponent()

	'    ' Add any initialization after the InitializeComponent() call.
	'    If Not System.Diagnostics.EventLog.SourceExists("MySource") Then
	'        System.Diagnostics.EventLog.CreateEventSource("MySource", _
	'        "MyNewLog")
	'    End If
	'    EventLog1.Source = "MySource"
	'    EventLog1.Log = "MyNewLog"

	'End Sub

	Private Sub t_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles t.Elapsed

		''search for a server instance
		'Dim a() As Process = Process.GetProcessesByName("Bf2_w32ded")

		''start a new server instance
		'If a.Length = 0 Then
		'	'Console.WriteLine("[{0}] starting server...", Now)
		'	'important: do NOT use AppWinStyle.NormalFocus,
		'	'which prevents the error message window to be the main window
		'	Shell("Bf2_w32ded.exe")
		'End If

		''CType(sender, Timer).Interval = My.Settings.Interval

		Logger.Write(String.Format("starting server: {0}", cmd))

		Dim pid As Integer
		Try
			'Shell(PathName:=cmd, Wait:=True)

			'don't use the following line because it does not work with current directory. see OnStart
			'proc = Diagnostics.Process.Start(cmd)

			pid = Shell(cmd)

		Catch ex As Exception
			LogError(ex.ToString())
		End Try

		'after successful execution save bf2dir to app.config
		If My.Settings.InstallDir <> bf2dir Then
			My.Settings.InstallDir = bf2dir
			My.Settings.Save()
		End If

		proc = Process.GetProcessById(pid)

		proc.WaitForExit()
		LogError("server crashed")

		CType(sender, Timer).Start()

	End Sub
End Class
